package com.le.tester.javaThink.fourth.concurrency;

import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * createTime：2021/12/23 9:47
 * description：管道提供线程间的输入和输出，线程间进行了通信，管道也是一个阻塞队列
 * PipedWriter and PipedReader
 */

//生产者
class Sender implements Runnable {

    private Random random = new Random(47);
    //必须连接一个PipedReader，整个管道才是能用的
    private PipedWriter pw = new PipedWriter();

    public PipedWriter getPipedWriter() {
        return pw;
    }

    @SuppressWarnings("InfiniteLoopStatement")
    @Override
    public void run() {
        try {
            while (true)
                for (char c = 'A'; c <= 'z'; c++) {
                    pw.write(c);
                    TimeUnit.MILLISECONDS.sleep(random.nextInt(500));
                }
        } catch (IOException e) {
            System.out.println(e.getMessage() + " Sender write exception");
        } catch (InterruptedException e) {
            System.out.println(e.getMessage() + " Sender sleep interrupted");
        }
    }
}

//消费者
class Receiver implements Runnable {

    private PipedReader pr;

    //读取生产者生产的消息，写进PipedReader；
    public Receiver(Sender sender) throws IOException {
        pr = new PipedReader(sender.getPipedWriter());
    }

    @SuppressWarnings("InfiniteLoopStatement")
    @Override
    public void run() {
        //读取生产者生产的消息
        try {
            while (true) {
                System.out.println("Read: " + (char) pr.read() + ", ");
            }
        } catch (Exception e) {
            //大概率抛出空指针异常
            System.out.println(e.getMessage() + " Receiver read exception");
        }
    }
}

public class PipedIO {
    public static void main(String[] args) throws Exception {
        Sender sender = new Sender();
        Receiver receiver = new Receiver(sender);
        //总是在线程池中使用了线程
        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(sender);
        exec.execute(receiver);
        TimeUnit.SECONDS.sleep(6);
        //运行7秒之后，线程会进行中断，读取完26个字母
        exec.shutdownNow();
    }
}
